[iOS 8] WKWebView で Web ページのロード中にステータスバーにインジケーターを表示してみる 〜 Objective-C 編
前回
前回の記事 では、WKWebView でWeb ページを表示する部分を解説しました。今回は通信中によくステータスバーに表示するインジケーターの表示方法について解説します。
サンプルプロジェクトを起動してみる
hirai-yuki/WebBrowserSample からサンプルプロジェクトをダウンロードして、Xcode 6 で開き、実行してみましょう(pod installを忘れずに!)。
すると、以下のように Web ページの読み込み中に、ステータスバーにインジケーターが表示されていますね。
このように、サンプルプロジェクトでは、WKWebView で Web ページを読み込んでいる最中に、ステータスバーにインジケーターを表示するようにしています。
それでは早速ソースコードを見てみましょう。
ソースコードを見る
と言っても、インジケーターの表示に関する記述は以下の3箇所しかありません。
CLMWebBrowserViewController.m WKWebView クラスの loading プロパティの変更を監視(KVO)
- (void)viewDidLoad { [super viewDidLoad]; // WKWebView インスタンスのプロパティの変更を監視する [self.webView addObserver:self forKeyPath:@"estimatedProgress" options:NSKeyValueObservingOptionNew context:nil]; [self.webView addObserver:self forKeyPath:@"title" options:NSKeyValueObservingOptionNew context:nil]; [self.webView addObserver:self forKeyPath:@"loading" options:NSKeyValueObservingOptionNew context:nil]; [self.webView addObserver:self forKeyPath:@"canGoBack" options:NSKeyValueObservingOptionNew context:nil]; [self.webView addObserver:self forKeyPath:@"canGoForward" options:NSKeyValueObservingOptionNew context:nil]; // 初回画面表示時にIntialURLで指定した Web ページを読み込む NSURL *url = [NSURL URLWithString:InitialURL]; NSURLRequest *request = [NSURLRequest requestWithURL:url]; [self.webView loadRequest:request]; } - (void)dealloc { // WKWebView インスタンスのプロパティの変更を監視を解除する [self.webView removeObserver:self forKeyPath:@"estimatedProgress"]; [self.webView removeObserver:self forKeyPath:@"title"]; [self.webView removeObserver:self forKeyPath:@"loading"]; [self.webView removeObserver:self forKeyPath:@"canGoBack"]; [self.webView removeObserver:self forKeyPath:@"canGoForward"]; }
CLMWebBrowserViewController.m インジケーターの表示/非表示を切り替えてるところ
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { if ([keyPath isEqualToString:@"estimatedProgress"]) { // estimatedProgressが変更されたら、プログレスバーを更新する [self.navigationController setSGProgressPercentage:self.webView.estimatedProgress * 100.0f]; } else if ([keyPath isEqualToString:@"title"]) { // titleが変更されたら、ナビゲーションバーのタイトルを設定する self.title = self.webView.title; } else if ([keyPath isEqualToString:@"loading"]) { // loadingが変更されたら、ステータスバーのインジケーターの表示・非表示を切り替える [UIApplication sharedApplication].networkActivityIndicatorVisible = self.webView.loading; // リロードボタンと読み込み停止ボタンの有効・無効を切り替える self.reloadButton.enabled = !self.webView.loading; self.stopButton.enabled = self.webView.loading; } else if ([keyPath isEqualToString:@"canGoBack"]) { // canGoBackが変更されたら、「<」ボタンの有効・無効を切り替える self.backButton.enabled = self.webView.canGoBack; } else if ([keyPath isEqualToString:@"canGoForward"]) { // canGoForwardが変更されたら、「>」ボタンの有効・無効を切り替える self.forwardButton.enabled = self.webView.canGoForward; } }
ご存知の方も多いと思いますが、そもそも、ステータスバーにインジケーターを表示するには、以下のように書きます。
// ステータスバーにインジケーターを表示する [UIApplication sharedApplication].networkActivityIndicatorVisible = YES; // ステータスバーのインジケーターを非表示にする [UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
サンプルプロジェクトで行なっていることを簡単に説明すると、「WKWebView クラスの loading プロパティの変更を監視して、ローディング中であればインジケーターを表示、そうでなければ非表示にする」ということをやっています。
WKWebView では loading が KVO に準拠した
サンプルプロジェクトだけ見ると、簡単なことしかやっていないように見えますが、実は非常に重要な点があります。 それは、WKWebView では loadingプロパティ が KVO に準拠したプロパティ になったことです。
実は、loading プロパティ自体は UIWebView にもあります。ただ、KVO に準拠していないため、上記のような実装ができませんでした。 なので、変わりに UIWebViewDelegate のメソッドを実装し、 Web ページのロード時・完了時に実行されるデリゲートメソッド内でインジケーターの表示・非表示を切り替えていました。
- (void)webViewDidStartLoad:(UIWebView*)webView { [UIApplication sharedApplication].networkActivityIndicatorVisible = YES; } - (void)webViewDidFinishLoad:(UIWebView*)webView { [UIApplication sharedApplication].networkActivityIndicatorVisible = NO; }
すごい細かいですが、こんな気の利いた変更もあるんですね!
まとめ
WKWebView では loading プロパティの他にも、KVOに準拠したプロパティがいくつかあります。 次回は、その1つである estimatedProgress プロパティを使用して、プログレスを表示するところを解説します。